package com.king.base;

import java.util.Set;

import com.google.common.base.Optional;

/**
 * Optional除了给null值命名所带来的代码可阅读性的提高，最大的好处莫过于Optional是傻瓜式的。
 * Optional对象的使用强迫你去积极的思考这样一种情况，如果你想让你的程序返回null值，这null值
 * 代表的含义是什么，因为你想要取得返回值，必然从Optional对象内部去获得，所以你必然会这么去思
 * 考。但是只是简单的使用一个Null值会很轻易的让人忘记去思索代码所要表达的含义到底是什么，尽管
 * FindBugs有些帮助，但是我们还是认为它并没有尽可能的解决好帮助程序员去思索null值代表的含义
 * 这个问题。
 *
 * 这种思考会在你返回某些存在的值或者不存在的值的时候显得特别相关。和其他人一样，你绝对很可能会
 * 忘记别人写的方法method(a,b)可能会返回一个null值，就好像当你去写method(a,b)的实现时，你
 * 也很可能忘记输入参数a也可以是null。如果返回的是Optional对象，对于调用者来说，就可以忘却怎
 * 么去度量null代表的是什么含义，因为他们始终要从optional对象中去获得真正的返回值。
 */
public class OptionalTest {

	public static void main(String[] args) {
		testOptional();
		testMethodReturn();
	}

	public static void testOptional() {
		// Optional.of(T)：获得一个Optional对象，其内部包含了一个非null的T数据类型实例，若T=null，则立刻报错。
		Optional<Integer> possible = Optional.of(6);
		// Optional.absent()：获得一个Optional对象，其内部包含了空值
		Optional<Integer> absentOpt = Optional.absent();
		// Optional.fromNullable(T)：将一个T的实例转换为Optional对象，T的实例可以不为空，也可以为空[Optional.fromNullable(null)，和Optional.absent()等价。
		Optional<Integer> NullableOpt = Optional.fromNullable(null);
		Optional<Integer> NoNullableOpt = Optional.fromNullable(10);
		// boolean isPresent()：如果Optional包含的T实例不为null，则返回true；若T实例为null，返回false
		if (possible.isPresent()) {
			System.out.println("possible isPresent:" + possible.isPresent());
			System.out.println("possible value:" + possible.get());
		}
		if (absentOpt.isPresent()) {
			System.out.println("absentOpt isPresent:" + absentOpt.isPresent());
		}
		if (NullableOpt.isPresent()) {
			System.out.println("fromNullableOpt isPresent:" + NullableOpt.isPresent());
		}
		if (NoNullableOpt.isPresent()) {
			System.out.println("NoNullableOpt isPresent:" + NoNullableOpt.isPresent());
		}
	}

	public static void testMethodReturn() {
		Optional<Long> value = method();
		if (value.isPresent()) {
			// T get()：返回Optional包含的T实例，该T实例必须不为空；否则，对包含null的Optional实例调用get()会抛出一个IllegalStateException异常
			System.out.println("获得返回值: " + value.get());
		} else {
			// T or(T)：若Optional实例中包含了传入的T的相同实例，返回Optional包含的该T实例，否则返回输入的T实例作为默认值
			System.out.println("获得返回值: " + value.or(-12L));
		}

		// T orNull()：返回Optional实例中包含的非空T实例，如果Optional中包含的是空值，返回null，逆操作是fromNullable()
		System.out.println("获得返回值 orNull: " + value.orNull());

		Optional<Long> valueNoNull = methodNoNull();
		if (valueNoNull.isPresent()) {
			// Set<T> asSet()：返回一个不可修改的Set，该Set中包含Optional实例中包含的所有非空存在的T实例，且在该Set中，每个T实例都是单态，如果Optional中没有非空存在的T实例，返回的将是一个空的不可修改的Set。
			Set<Long> set = valueNoNull.asSet();
			System.out.println("获得返回值 set 的 size : " + set.size());
			System.out.println("获得返回值: " + valueNoNull.get());
		} else {
			System.out.println("获得返回值: " + valueNoNull.or(-12L));
		}

		System.out.println("获得返回值 orNull: " + valueNoNull.orNull());
	}

	private static Optional<Long> method() {
		return Optional.fromNullable(null);
	}

	private static Optional<Long> methodNoNull() {
		return Optional.fromNullable(15L);
	}
}